from __future__ import division
from main import assured
from search import aStarSearchAux
from search import aStarSearch
from ways import load_map_from_csv
from numpy import *
from assured import *
import matplotlib.pyplot as plt
import pygmaps

'''
/* name: areConnected
/* Descriprion: checks if there is a path between 2 junctions
/* paramIn: roads - roads map
/* paramIn: start - first junction
/* paramIn: end - last junction
/* return: true if there is a pathm false otherwise
'''
def areConnected(roads, start, end):
    visited, stack = set(), [start]
    while stack:
        vertex = stack.pop()
        if vertex == end:
            return True
        if vertex not in visited:
            visited.add(vertex)
            stack.extend(set(listOfLinks(roads[vertex])) - visited)
    return False

'''
/* name: listOfLinks
/* Descriprion: returns a list of the links a junctiom had
/* paramIn: junction - junction of which links are returned
/* return: list of links a junction has
'''
def listOfLinks(junction):
    links = []
    for link in junction.links:
        links.append(link.target)
    return links

'''
/* name: random20Problems
/* Descriprion: generates 20 random problems and prints: 1) for each problem - the real cost of the best path
                                                         2) for each problem - the huristic guess for the cost of the path
                                                         3) a graph desbribes the above values for each problem
/* return: None
'''
def random20Problems():
    roads = load_map_from_csv('israel.csv',0,100)
    rangeOfJunctions = len(roads)
    hList=[]
    gList=[]
    i = 0
    while i < 20:
        junction1 = random.randint(0,rangeOfJunctions)
        junction2 = random.randint(0,rangeOfJunctions)
        if(junction1 != junction2 and areConnected(roads, junction1, junction2)):
            result = aStarSearchAux(junction1, junction2,0, roads)
            totalGcost = result[1]
            totalHcost = result[2]
            gList.append(totalGcost)
            hList.append(totalHcost)
            i += 1
    plt.plot(hList,gList,'ro', gList, gList, 'r--')
    plt.ylabel('actual driving time')
    plt.xlabel('estimated driving time')

    plt.show()

def getAverageTime(source, dest, numSamples, roads):
    path = aStarSearch(source, dest, 0, roads)
    avgTime = 0
    for sample in range(numSamples):
        roads.generation = sample
        avgTime += calculateDriveTime(path, roads)
    return avgTime/numSamples

'''
/* name: random20Problems_assured
/* Descriprion: generates 20 random problems and prints: 1) for each problem - the real cost of the best path
                                                         2) for each problem - the huristic guess for the cost of the path
                                                         3) a graph desbribes the above values for each problem
/* return: None
'''
def randomProblemsAssured(roads=None):
    if not roads:
        roads = load_map_from_csv('israel.csv',0,10000)
    numSamples = 100
    numJunctions = len(roads)

    i = 0
    errorCounter = 0
    reqlist=[]
    gotlist=[]
    potentialPaths = []
    noPath = True
    while i < 100:
        junction1 = random.randint(0,numJunctions)
        junction2 = random.randint(0,numJunctions)
        if(junction1 != junction2 and areConnected(roads, junction1, junction2)):
            # print "started test no. ", i
            requestedTime = getAverageTime(junction1, junction2,numSamples,roads) #averaging all samples on one (arbitrary) path
            roads.generation = 1
            res = runAssured(source = junction1, target= junction2, confidence=0.5, maxTime=requestedTime, roads = roads)
            assuredPath = res[0]
            potentialPaths = res[1]
            assuredTime = calculateDriveTime(assuredPath, roads)
            gotlist.append(assuredTime)
            reqlist.append(requestedTime)
            # if noPath and len(potentialPaths) >= 3:
            #     print "potential paths[0]: ", potentialPaths[0]
            #     print "potential paths[1]: ", potentialPaths[1]
            #     print "potential paths[2]: ", potentialPaths[2]
            #     noPath = False
            if assuredTime > requestedTime:
                errorCounter += 1
            i += 1
    plt.plot(reqlist,gotlist ,'ro', reqlist, reqlist, 'r')
    plt.xlabel('requested driving time')
    plt.ylabel('retrieved driving time')
    plt.show()

    print "error percenage = ", (errorCounter/numSamples)
    return potentialPaths


'''
/* name: computeRealTime
/* Descriprion: computes actual driving time for a given path
/* paramIn: roads - roads map
/* paramIn: path - the path to compute the time for
/* return: ctual driving time for path
'''
def computeRealTime(roads, path):
    totalTime = 0
    i=1
    for x in path:
        if i==len(path):
            return totalTime
        for link in roads[x].links:
           if link.target == path[i]:
                totalTime += ((link.distance/1000)/(roads.link_speed(link)))*60
                i += 1
                break
'''
/* name: showDifferenceOfLights
/* Descriprion: generates a problem that had different solution when considering lights (best path has less lights)
        and when not considering lights (only consideration for best path is time)
        prints the 2 paths found
/* return: None
'''
def showDifferenceOfLights():
    noLightsConsideration = []
    withLightsConsideration = []
    roads = load_map_from_csv('israel.csv',0,40000)

    #keep going until you find a problem that produce different paths for the with and without lights consideration
    while True:
        rangeOfJunctions = len(roads)
        junction1 = random.randint(0,rangeOfJunctions)
        junction2 = random.randint(0,rangeOfJunctions)
        if(junction1 != junction2 and areConnected(roads, junction1, junction2)):
            noLightsConsideration = aStarSearchAux(junction1, junction2, 0, roads)
             #weight for lights is high but not 1 - we went the driving time to have impact also
            withLightsConsideration = aStarSearchAux(junction1, junction2, 0.8, roads)
            if(noLightsConsideration[0] != withLightsConsideration[0]):
                noLightsConsiderationLat = [roads[x].lat for x in noLightsConsideration[0]]
                noLightsConsiderationLon = [roads[x].lon for x in noLightsConsideration[0]]
                noLightsConsiderationZip = zip(noLightsConsiderationLat, noLightsConsiderationLon)
                noLightsConsiderationLights = []
                for x in range(len(noLightsConsideration[0])):
                    currentJunction = (noLightsConsideration[0])[x]
                    if roads.has_traffic_lights(roads[currentJunction]):
                        noLightsConsiderationLights.append(noLightsConsiderationZip[x])

                withLightsConsiderationLat = [roads[x].lat for x in withLightsConsideration[0]]
                withLightsConsiderationLon = [roads[x].lon for x in withLightsConsideration[0]]
                withLightsConsiderationZip = zip(withLightsConsiderationLat, withLightsConsiderationLon)
                withLightsConsiderationLights = []
                for x in range(len(withLightsConsideration[0])):
                    currentJunction = (withLightsConsideration[0])[x]
                    if roads.has_traffic_lights(roads[currentJunction]):
                        withLightsConsiderationLights.append(withLightsConsiderationZip[x])
                mymap = pygmaps.maps(noLightsConsiderationLat[0], noLightsConsiderationLon[0], 5)
                mymap.addpath(noLightsConsiderationZip, "#00FF00") #green
                mymap.addpath(withLightsConsiderationZip,"#0000FF") #blue

                #find common parts
                commonPart=[]
                for junction in withLightsConsiderationZip:
                    if junction in noLightsConsiderationZip:
                        commonPart.append(junction)

                #add pink points for the common parts
                for x in commonPart:
                    mymap.addpoint(x[0], x[1], "#FF00FF")

                #add red points for traffic lights in the path without lights consideration
                for x in noLightsConsiderationLights:
                    mymap.addpoint(x[0], x[1], "#FF0000")

                 #add red points for traffic lights in the path with lights consideration
                for x in withLightsConsiderationLights:
                    mymap.addpoint(x[0], x[1], "#FF0000")
                #add lights:
                mymap.draw('./mymap2.html')
                print(computeRealTime(roads, noLightsConsideration[0]))
                print(computeRealTime(roads, withLightsConsideration[0]))
                break

def showConsideredPaths():
    roads = load_map_from_csv('israel.csv',100,10000)
    threePaths = randomProblemsAssured(roads)[:3]
    print
    #threePaths = [
    #                [4747, 4746, 4745, 4744, 4743, 4742, 3578, 3579, 3580, 3581, 3582, 3583, 3584, 3585, 3586, 3587, 3588, 3589, 3590, 3591, 3592, 3593, 4968, 5113, 5025, 5112, 4551, 4550, 4549, 4548, 3833, 3931, 3932, 3480, 3933, 3915, 3934, 3935, 3936, 5036, 5037, 4608, 4609, 4610, 4611, 4612, 4613, 4614, 4615, 4616, 4617, 4313, 4141, 4140, 4139, 4138, 4137, 4136, 4135, 4134],
    #                [4747, 4746, 4745, 4744, 4743, 4742, 3578, 3579, 3580, 3581, 3582, 3583, 3584, 3585, 3586, 3587, 3588, 3589, 3590, 3591, 3592, 3593, 4968, 4387, 4494, 5108, 3644, 5109, 5110, 5111, 4551, 4550, 4549, 4548, 3833, 3931, 3932, 3480, 3933, 3915, 3934, 3935, 3936, 5036, 5037, 4608, 4609, 4610, 4611, 4612, 4613, 4614, 4615, 4616, 4617, 4313, 4141, 4140, 4139, 4138, 4137, 4136, 4135, 4134],
    #                [4747, 4746, 4745, 4744, 4743, 4742, 3578, 3579, 3580, 3581, 3582, 3583, 3584, 3585, 3586, 3587, 3588, 3589, 3590, 3591, 3592, 3593, 4968, 5113, 5025, 5112, 4551, 4550, 4549, 4548, 3833, 3931, 3932, 3480, 3933, 3915, 3934, 3935, 3936, 5035, 3921, 5034, 5033, 5039, 4944, 5038, 4608, 4609, 4610, 4611, 4612, 4613, 4614, 4615, 4616, 4617, 4313, 4312, 4311, 4310, 4309, 4308, 4307, 4306, 4305, 4304, 4303, 4314, 4141, 4140, 4139, 4138, 4137, 4136, 4135, 4134]
    #]

    #each is a ist of lists (list of paths)
    threePathsLat = []
    threePathsLon= []
    threePathsZip = []

    for i in range(len(threePaths)):
        threePathsLat.append([roads[x].lat for x in threePaths[i]])
        threePathsLon.append([roads[x].lon for x in threePaths[i]])
        threePathsZip.append(zip(threePathsLat[i], threePathsLon[i]))

    mymap = pygmaps.maps(threePathsLat[0][0], threePathsLon[0][0], 10)
    colors = ["#45629E","#CC0000","#5A935A"]
    for i in range(len(threePaths)):
        print threePathsZip[i]
        mymap.addpath(threePathsZip[i], colors[i])

    mymap.addpoint(threePathsLat[0][0], threePathsLon[0][0], "#70DBFF")
    mymap.addpoint(threePathsLat[0][-1], threePathsLon[0][-1], "#FF0066")
    mymap.draw('./mymap2.html')

if __name__ == '__main__':
    from sys import argv
    # randomProblemsAssured()
    # random20Problems()
    # showConsideredPaths()
    # howDifferenceOfLights()
    roads = load_map_from_csv()
    path = aStarSearchAux(5500, 55000,0,roads)
    print "sdasdas", 3


